package world.snowcrystal.configuration;

import org.redisson.Redisson;
import org.redisson.api.*;
import org.redisson.config.Config;
import org.redisson.spring.transaction.RedissonTransactionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import world.snowcrystal.dto.ChatroomMessage;
import world.snowcrystal.dto.ChatroomUser;
import world.snowcrystal.dto.RegistrationRequestMessage;
import world.snowcrystal.properties.AuthenticationProperties;
import world.snowcrystal.properties.ChatroomProperties;

import java.time.Duration;

@Configuration
@EnableConfigurationProperties(ChatroomProperties.class)
public class RedisConfigure {


    @Autowired
    private ChatroomProperties chatroomProperties;

    @Autowired
    private AuthenticationProperties authenticationProperties;

    @Value("${spring.data.redis.host}")
    private String redisHost;

    @Value("${spring.data.redis.password}")
    private String redisPasswd;


    @Bean(destroyMethod = "shutdown")
    public RedissonClient redisson() {
        Config config = new Config();
        config.useSingleServer()
                .setAddress("redis://" + redisHost + ":6379")
                .setPassword(redisPasswd)
                .setDatabase(0)
                .setConnectionMinimumIdleSize(4)
                .setPingConnectionInterval(3000)
                .setTimeout(4125)
                .setRetryAttempts(3)
                .setRetryInterval(1200)
                .setConnectTimeout(4000);
        return Redisson.create(config);
    }


    @Bean
    public RedissonTransactionManager redissonTransactionManager(RedissonClient redisson) {
        return new RedissonTransactionManager(redisson);
    }


    @Bean
    @Lazy
    @ConditionalOnClass(RedissonClient.class)
    public RBloomFilter<String> bloomFilter(RedissonClient redisson) {
        int total = 1000000;
        double precision = 0.01;
        RBloomFilter<String> bm = redisson.getBloomFilter("Snowcrystal-Bloom-Filter");
        if (!bm.isExists()) {
            bm.tryInit(total, precision);
        }
        if (!bm.contains("tianqing")) {
            bm.add("tianqing");
        }
        return bm;
    }

//    @Bean
//    @Lazy
//    @ConditionalOnClass(RedisConfigure.class)
//    public RMapCache<String,UserAuthenticationDetails> mapCache(RedissonClient redisson) {
//        MapCacheOptions<String, UserAuthenticationDetails> options = MapCacheOptions.name("users");
//        options.writeMode(WriteMode.WRITE_BEHIND)
//                .writeBehindBatchSize(1);
//        return redisson.getMapCache(options);
//    }


//    @Bean
//    @Lazy
//    public RTopic topic(RedissonClient redisson){
//        return redisson.getTopic(chatroomProperties.getChatroomChannel()).;
//    }


    @Bean
    @Lazy
    @ConditionalOnClass(RedissonClient.class)
    public RList<ChatroomMessage> redisChatroomMessageCache(RedissonClient redisson) {
//        RScoredSortedSet<ChatroomMessage> scoredSortedSet = redisson.getScoredSortedSet(chatroomProperties.getChatroomCacheSet());

//        scoredSortedSet.expireIfNotSet(Duration.of(chatroomProperties.getChatroomMessageExpirationTime(),
//                chatroomProperties.getChatroomMessageExpirationTimeUnit()));
        final RList<ChatroomMessage> list = redisson.getList(chatroomProperties.getChatroomCacheSet());
        list.expireIfNotSet(Duration.of(chatroomProperties.getChatroomMessageExpirationTime(),
                chatroomProperties.getChatroomMessageExpirationTimeUnit()));
        return list;
    }


    @Bean
    @Lazy
    @ConditionalOnClass(RedissonClient.class)
    public RMapCache<String, ChatroomUser> chatroomOnlineUserCache(RedissonClient redisson) {
        RMapCache<String, ChatroomUser> mapCache = redisson.getMapCache(chatroomProperties.getChatroomUserCacheSet());
        mapCache.setMaxSize(Integer.MAX_VALUE);
        return mapCache;
    }

    @Bean
    @Lazy
    @ConditionalOnClass(RedissonClient.class)
    public RMapCache<String, RegistrationRequestMessage> mailVerificationQueue(RedissonClient redisson) {

        RMapCache<String, RegistrationRequestMessage> mapCache = redisson.getMapCache(authenticationProperties.getMailVerificationQueueName());
        mapCache.setMaxSize(Integer.MAX_VALUE);
        return mapCache;
    }

    @Bean
    @Lazy
    @ConditionalOnClass(RedissonClient.class)
    public RSetCache<String> inPlaceTokenList(RedissonClient redisson) {
        return redisson.getSetCache(authenticationProperties.getInPlaceOperationTokenBucketName());
    }


}
